package com.jandar.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.Locale;
import java.util.regex.Pattern;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.border.TitledBorder;

import jp.gr.java_conf.ussiy.app.propedit.PropertiesEditor;

import com.jandar.Resources;
import com.jandar.Watcher;
import com.jandar.logging.LoggerFactory;
import com.jandar.logging.impl.FileLogger;
import com.jandar.util.DateUtils;
import com.jandar.util.ExceptionUtils;
import com.jandar.util.FileUtils;

/**
 * 应用程序主界面。
 * 
 * @author pqj
 * @version 2009-7-9
 */
public class GUIWatcher extends JFrame {

	// 使用静态引用的说明（为了让大家不要误解）：
	// 该引用的目的：为了修改状态栏的显示，需要在Task里面调用GUI。
	// 问题是：如何在Task中得到GUI的引用？
	// 1）没有使用传递引用到Watcher
	// 因为，GUI只是提供一个图形界面给用户另一方面是为了使用Watcher展现出一个效果，Watcher不应该倒过来引用GUI对象，
	// 而且，当作为WEB方式运行的话，Watcher是和GUI没有任何关系的，所以，没有使用传递引用的方式。
	// 2）没有使用单例模式
	// 单例模式确实可以在任何类中调用得到该单例对象，而GUI主界面确实不会用到两个对象界面对象。做成单例为何不可以？
	// 单例模式是肯定会创建一个对象出来的，当使用WEB方式的时候运行的话，那岂不是又出现了APP程序了。
	/** 提供一个对外指针访问主界面 */
	public static GUIWatcher THIS_OBJECT = null;

	/** serialVersionUID */
	private static final long serialVersionUID = 2912008747673914230L;
	
	private static final String MSG_DEFAULT_STATUSBAR = "欢迎使用文件导入器！";

	private static final int WIDTH = 550;

	private static final int HEIGHT = 350;

	// private static final String PATH_PATTERN = "^\\S:((\\\\|/)\\S+)*(\\\\|/)\\S+.[lL][oO][gG]$";
	private static final String PATH_PATTERN = "^\\S:((\\\\|/)\\S*)*$";

	private JPanel mainPanel = new JPanel();

	private JPanel panel_1 = new JPanel();

	private JPanel panel_2 = new JPanel();

	private JPanel panel_3 = new JPanel();

	private JPanel panel_4 = new JPanel();

	private JTextField stateText = new JTextField();

	private DeckTextField loggerText = new DeckTextField(30);

	private JButton viewLoggerBut = new JButton("查看");

	private JButton locLoggerBut = new JButton("浏览");

	private JButton startBut = new JButton("启动");

	private JButton stopBut = new JButton("停止");

	private DeckTextField startTimeText = new DeckTextField(20);

	private DeckTextField periodText = new DeckTextField(10);

	private DeckStatusBar statusBar = new DeckStatusBar(200, true, true);

	private EncoderDialog encoderDialog = null;

	private JMenu fileMenu = new JMenu("文件(F)");

	private JMenu toolMenu = new JMenu("工具(T)");

	private JMenu helpMenu = new JMenu("帮助(H)");

	private JMenuItem itemCfg = new JMenuItem("系统配置");

	private JMenuItem itemEncoder = new JMenuItem("URL加密工具...");

	private JMenuItem itemOpenTableCfg = new JMenuItem("数据库表结构配置");

	private JMenuItem itemOpenImportDir = new JMenuItem("打开导入文件夹");

	private JMenuItem itemOpenFinishDir = new JMenuItem("打开成功文件夹");

	private JMenuItem itemOpenErrorDir = new JMenuItem("打开失败文件夹");

	private JMenuItem itemOpenLogDir = new JMenuItem("打开日志文件夹");

	private JMenuItem itemExit = new JMenuItem("退出(X)");

	private JMenuItem itemAbout = new JMenuItem("关于...(A)");

	private transient Watcher watcher = null;

	public GUIWatcher() {
		FlowLayout layout = (FlowLayout) panel_1.getLayout();
		layout.setAlignment(FlowLayout.LEFT);
		panel_1.setBorder(BorderFactory.createTitledBorder(null, "定时器",
				TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, new Font(
						"Dialog", Font.BOLD, 12), new Color(51, 51, 51)));

		layout = (FlowLayout) panel_2.getLayout();
		layout.setAlignment(FlowLayout.LEFT);
		panel_2.setBorder(BorderFactory.createTitledBorder(null, "日志",
				TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, new Font(
						"Dialog", Font.BOLD, 12), new Color(51, 51, 51)));

		panel_3.setBorder(BorderFactory.createTitledBorder(null, "控制",
				TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, new Font(
						"Dialog", Font.BOLD, 12), new Color(51, 51, 51)));

		panel_4.setBorder(BorderFactory.createTitledBorder(null, "状态显示",
				TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, new Font(
						"Dialog", Font.BOLD, 12), new Color(51, 51, 51)));

		panel_1.add(new JLabel("启动时间："));
		panel_1.add(startTimeText);
		panel_1.add(new JLabel("间隔(ms)："));
		panel_1.add(periodText);
		panel_2.add(new JLabel("日志目录："));
		panel_2.add(loggerText);
		panel_2.add(viewLoggerBut);
		panel_2.add(locLoggerBut);
		panel_3.add(startBut);
		panel_3.add(stopBut);
		stateText.setToolTipText("状态显示");
		stateText.setHorizontalAlignment(JTextField.CENTER);
		stateText.setBackground(Color.BLACK);
		stateText.setForeground(Color.RED);
		setStopState();
		panel_4.setLayout(new BorderLayout());
		panel_4.add(stateText, BorderLayout.CENTER);
		GridLayout mainPanelLayout = new GridLayout(4, 1);
		mainPanelLayout.setVgap(2);
		mainPanel.setLayout(mainPanelLayout);
		mainPanel.add(panel_4);
		mainPanel.add(panel_1);
		mainPanel.add(panel_2);
		mainPanel.add(panel_3);
		statusBar.setText(MSG_DEFAULT_STATUSBAR);
		statusBar
				.setMqrqueeFill("                                                                                             ");
		statusBar.setLabelColor(Color.BLUE);

		this.getContentPane().add(mainPanel, BorderLayout.CENTER);
		this.getContentPane().add(statusBar, BorderLayout.SOUTH);

		// 从配置文件初始化
		loggerText.setText(LoggerFactory.getFilePath());
		startTimeText.setText(Resources.getInstance().getStartTimeStr());
		periodText.setText(String.valueOf(Resources.getInstance().getPeriod()));
		startTimeText.defaultFocusCallback();
		periodText.defaultFocusCallback();
		loggerText.defaultFocusCallback();

		startTimeText.setToolTipText("启动时间");
		startTimeText.addFocusListener(new FocusListener() {
			boolean errorFlg = false;

			public void focusGained(FocusEvent e) {
				startTimeText.inputFocusCallback();
				if (errorFlg) {
					setReportState("启动时间格式错误！格式：yyyy-MM-dd HH:mm:ss");
				} else {
					setReportState("定时器启动时间");
				}
			}

			public void focusLost(FocusEvent e) {
				try {
					DateFormat format = DateUtils.getDateFormat(Resources.DEFAULT_DATE_PATTERN,
							Locale.CHINA);
					format.parse(startTimeText.getText());
					startTimeText.defaultFocusCallback();
					errorFlg = false;
				} catch (ParseException e1) {
					startTimeText.errorFocusCallback();
					errorFlg = true;
				}
			}
		});

		periodText.setToolTipText("间隔(ms)");
		periodText.addFocusListener(new FocusListener() {
			boolean errorFlg = false;

			public void focusGained(FocusEvent e) {
				periodText.inputFocusCallback();
				if (errorFlg) {
					setReportState("间隔时间格式错误！间隔时间是一个毫秒数。");
				} else {
					setReportState("定时器间隔时间");
				}
			}

			public void focusLost(FocusEvent e) {
				try {
					Long.parseLong(periodText.getText());
					periodText.defaultFocusCallback();
					errorFlg = false;
				} catch (NumberFormatException e1) {
					periodText.errorFocusCallback();
					errorFlg = true;
				}
			}
		});

		loggerText.setToolTipText("日志目录");
		loggerText.addFocusListener(new FocusListener() {
			boolean errorFlg = false;

			public void focusGained(FocusEvent e) {
				loggerText.inputFocusCallback();
				if (errorFlg) {
					setReportState("日志目录格式错误！例如：c:/a/b/");
				} else {
					setReportState("日志文件目录");
				}
			}

			public void focusLost(FocusEvent e) {
				if (!Pattern.matches(PATH_PATTERN, loggerText.getText())) {
					loggerText.errorFocusCallback();
					errorFlg = true;
				} else {
					loggerText.defaultFocusCallback();
					errorFlg = false;
				}
			}
		});

		// 查看按钮
		viewLoggerBut.setToolTipText("查看");
		viewLoggerBut.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				setReportState("查看日志文件");
				File file = FileLogger.getDirLogFile(loggerText.getText());
				if (file == null) {
					JOptionPane.showMessageDialog(GUIWatcher.this, "日志文件不存在！", "消息",
							JOptionPane.INFORMATION_MESSAGE);
				} else {
					try {
						Runtime.getRuntime().exec(
								new String[] { "notepad.exe", file.getAbsolutePath() });
					} catch (IOException e1) {
						ExceptionUtils.error(e1);
					}
				}
			}
		});

		// 浏览按钮
		locLoggerBut.setToolTipText("浏览");
		locLoggerBut.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				setReportState("浏览日志目录");
				File dir = new File(loggerText.getText());
				if (!dir.exists()) {
					dir.mkdir();
				}

				openFile(loggerText.getText());
			}
		});

		// 启动按钮
		startBut.setToolTipText("启动");
		startBut.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				try {
					setStartState();
					Resources resources = Resources.getInstance();
					resources.reload();
					DateFormat format = DateUtils.getDateFormat(Resources.DEFAULT_DATE_PATTERN,
							Locale.CHINA);
					Date startDate = format.parse(startTimeText.getText());
					resources.setStartTime(startDate);
					resources.setPeriod(Long.parseLong(periodText.getText()));
					LoggerFactory.setFilePath(loggerText.getText());
					watcher = new Watcher();
					watcher.start();
					startTimeText.setEnabled(false);
					periodText.setEnabled(false);
					itemCfg.setEnabled(false);
					itemEncoder.setEnabled(false);
					startBut.setEnabled(false);
					stopBut.setEnabled(true);
					loggerText.setEnabled(false);
					statusBar.setText(MSG_DEFAULT_STATUSBAR);
				} catch (Exception e1) {
					ExceptionUtils.error(e1);
					stopOperate();
					setStopState();
				}
			}
		});

		// 停止按钮
		stopBut.setToolTipText("停止");
		stopBut.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				stopOperate();
				setStopState();
			}
		});
		stopBut.setEnabled(false);

		// 窗口关闭事件
		this.addWindowListener(new WindowAdapter() {

			public void windowOpened(WindowEvent e) {
				startBut.requestFocus();
			}

			public void windowClosing(WindowEvent e) {
				try {
					if (watcher != null) {
						watcher.stop();
					}
				} finally {
					System.exit(0);
				}
			}
		});

		// 菜单初始化
		JMenuBar menuBar = new JMenuBar();
		fileMenu.add(itemExit);
		toolMenu.add(itemCfg);
		toolMenu.add(itemOpenTableCfg);
		toolMenu.add(itemEncoder);
		toolMenu.add(itemOpenImportDir);
		toolMenu.add(itemOpenFinishDir);
		toolMenu.add(itemOpenErrorDir);
		toolMenu.add(itemOpenLogDir);
		helpMenu.add(itemAbout);
		fileMenu.setMnemonic(KeyEvent.VK_F);
		itemExit.setMnemonic(KeyEvent.VK_X);
		helpMenu.setMnemonic(KeyEvent.VK_H);
		itemAbout.setMnemonic(KeyEvent.VK_A);
		toolMenu.setMnemonic(KeyEvent.VK_T);
		itemCfg.setAccelerator(KeyStroke.getKeyStroke("F5"));
		itemOpenTableCfg.setAccelerator(KeyStroke.getKeyStroke("F6"));
		itemEncoder.setAccelerator(KeyStroke.getKeyStroke("F7"));
		itemOpenImportDir.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, KeyEvent.CTRL_MASK));
		itemOpenFinishDir.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, KeyEvent.CTRL_MASK));
		itemOpenErrorDir.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_3, KeyEvent.CTRL_MASK));
		itemOpenLogDir.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_4, KeyEvent.CTRL_MASK));
		menuBar.add(fileMenu);
		menuBar.add(toolMenu);
		menuBar.add(helpMenu);
		this.setJMenuBar(menuBar);

		// 打开数据库表结构配置
		itemOpenTableCfg.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				String filePath = GUIWatcher.class.getResource(Resources.TABLE_CONFIG).getFile();
				try {
					filePath = URLDecoder.decode(filePath, "utf-8");
				} catch (UnsupportedEncodingException e1) {
					ExceptionUtils.error(e1);
				}
				File file = new File(filePath);
				openFile(file.getAbsolutePath());
			}
		});

		// 打开导入文件夹菜单
		itemOpenImportDir.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				FileUtils.checkAndNewFile(FileUtils.getInstance().getInfolder());
				openFile(Resources.getInstance().getInfolder().getAbsolutePath());
			}
		});

		// 打开成功文件夹菜单
		itemOpenFinishDir.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				FileUtils.checkAndNewFile(FileUtils.getInstance().getOutfolder());
				openFile(Resources.getInstance().getOutfolder().getAbsolutePath());
			}
		});

		// 打开错误文件夹菜单
		itemOpenErrorDir.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				FileUtils.checkAndNewFile(FileUtils.getInstance().getErrfolder());
				openFile(Resources.getInstance().getErrfolder().getAbsolutePath());
			}
		});

		// 打开日志文件夹菜单
		itemOpenLogDir.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				FileUtils.checkAndNewFile(new File(loggerText.getText()));
				openFile(loggerText.getText());
			}
		});

		// 关于菜单
		itemAbout.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				JOptionPane.showMessageDialog(GUIWatcher.this,
						"文件导入器（共享版）v1.0.0\r\nauthor:   iPan\r\nemail:    568159412@qq.com\r\nupdate:  2009-7-31\r\n", "消息",
						JOptionPane.INFORMATION_MESSAGE);
			}
		});

		// 退出菜单
		itemExit.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				stopOperate();
				System.exit(0);
			}
		});

		// 配置菜单
		itemCfg.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				URL url = GUIWatcher.class.getResource(Resources.CONFIG);
				if (url == null) {
					JOptionPane.showMessageDialog(null, "配置文件找不到！", "消息",
							JOptionPane.WARNING_MESSAGE);
				}
				String filePath = url.getFile();
				try {
					filePath = URLDecoder.decode(filePath, "utf-8");
				} catch (UnsupportedEncodingException e1) {
					ExceptionUtils.error(e1);
				}
				File file = new File(filePath);
				new PropertiesEditor(new String[] { file.getAbsolutePath() });
			}
		});

		// 加密菜单
		if (!Resources.getInstance().isUrlEncrypt()) {
			itemEncoder.setEnabled(false);
		}
		itemEncoder.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				if (encoderDialog == null) {
					encoderDialog = new EncoderDialog(GUIWatcher.this);
				}

				// 屏幕的大小取得
				Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
				encoderDialog.setLocation(
						(int) (screenSize.getWidth() - encoderDialog.getWidth()) / 2,
						(int) (screenSize.getHeight() - encoderDialog.getHeight()) / 2);
				encoderDialog.setVisible(true);
			}
		});

		//this.pack();
		this.setSize(WIDTH, HEIGHT);
		this.setResizable(false);
		this.setTitle("文件导入器（共享版）");
		// 测试*.png文件找不到，.jpg,.gif能找到
		this.setIconImage(Toolkit.getDefaultToolkit().createImage(
				GUIWatcher.class.getResource("/icons/title.gif")));
		// 屏幕的大小取得
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		this.setLocation((int) (screenSize.getWidth() - this.getWidth()) / 2, (int) (screenSize
				.getHeight() - this.getHeight()) / 2);
		this.setVisible(true);
	}

	private void openFile(String path) {
		try {
			String wrapPath = "\"" + path + "\"";
			Runtime.getRuntime().exec(new String[] { "cmd.exe", "/c start \"\" " + wrapPath });
		} catch (IOException e) {
			ExceptionUtils.error(e);
		}
	}

	public void stopOperate() {
		if (watcher != null) {
			watcher.stop();
		}
		startTimeText.setEnabled(true);
		periodText.setEnabled(true);
		itemCfg.setEnabled(true);
		if (Resources.getInstance().isUrlEncrypt()) {
			itemEncoder.setEnabled(true);
		}
		startBut.setEnabled(true);
		loggerText.setEnabled(true);
		stopBut.setEnabled(false);
		try {
			// Task内最长延迟500ms
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public void setStartState() {
		setStateText("启动状态", Color.GREEN);
	}

	public void setStopState() {
		setStateText("停止状态", Color.RED);
	}

	public void setWatchState(String text) {
		setStateText(text, Color.GREEN);
	}

	public void setReportState(String text) {
		setStateText(text, Color.RED);
	}

	public void setStateText(String text, Color color) {
		stateText.setForeground(color);
		stateText.setText(text);
	}

	public String getStateTextValue() {
		return stateText.getText();
	}

	public Color getStateColor() {
		return stateText.getForeground();
	}

	public void setStatusBarText(String text) {
		statusBar.setText(text);
	}

	public String getStatusBarText() {
		return statusBar.getText();
	}

	public static void main(String[] args) throws Exception {
		Class.forName("com.jandar.Resources");
		UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		THIS_OBJECT = new GUIWatcher();
	}
}
